//! @Author: DengLibin
//! @Date: Create in 2025-02-07 16:20:03
//! @Description: 下载file_recorde中的附件

use std::sync::Arc;

use anyhow::Ok;
use log::info;
use my_util_lib::{date, file_util, http};
use tokio::{sync::Semaphore, task};

use crate::{
    dao::sqlite::sqlite_dao,
    sys::global::{to_global_result, GlobalResult},
};

//下载文件并发数
const MAX_CONCURRENT_DOWNLOADS: usize = 3;

pub async fn start(sqlite_url: &str) -> GlobalResult<()> {
    // let sqlite_url = "sqlite:file_record.db";
    let sqlite_conn_pool: sqlx::Pool<sqlx::Sqlite> = sqlite_dao::get_conn_pool(sqlite_url).await?;
    let mut id_start = 636117205176455_i64;
    let mut count = 0;
    loop {
        let sql = format!(
            "select * from  file_record where id < {} order by id desc limit 50",
            id_start
        );
        let rows = sqlite_dao::query_sql::<super::FileRecord>(&sql, &sqlite_conn_pool).await?;
        if rows.is_empty() {
            break;
        }
        download_files(&rows).await?;
        count += rows.len();
        id_start = rows.last().unwrap().id;

        info!("进度:{}", count);
    }

    Ok(())
}

/// @Author: DengLibin
/// @Date: Create in 2025-02-07 16:49:54
/// @Description: 下载多个文件
async fn download_files(file_records: &Vec<super::FileRecord>) -> GlobalResult<()> {
    //控制并发
    let semaphore = Arc::new(Semaphore::new(MAX_CONCURRENT_DOWNLOADS));

    let mut handles = Vec::new();

    for file_record in file_records.iter() {
        let path = file_record.path.to_string();
        //本地路径
        let local_path = get_local_path(path.clone().as_str()).await?;
        if file_util::exist(&local_path) {
            continue;
        }

        let permit = semaphore.clone().acquire_owned().await.unwrap();

        let handle = task::spawn(async move {
            let r = down_file(path.clone(), local_path).await;
            if let Err(_e) = r {
                // error!("下载文件异常:{}", path);
            }
            drop(permit); // 显式释放信号量
        });

        handles.push(handle);
    }

    // 等待所有任务完成
    for handle in handles {
        let _ = handle.await;
    }

    info!("All downloads completed.");

    Ok(())
}

/// @Author: DengLibin
/// @Date: Create in 2025-02-07 16:57:55
/// @Description: 下载单个文件
async fn down_file(path: String, local_path: String) -> GlobalResult<()> {
    let url = format!("http://118.122.86.16:8200/minio/yiscn/{}", path);
    let http_client = http::HttpClient::new();
    let r = http_client.download_by_stream(&url, &local_path).await;

    to_global_result(r)
}

/// @Author: DengLibin
/// @Date: Create in 2025-02-07 17:00:54
/// @Description: 本地路径
async fn get_local_path(file_name: &str) -> GlobalResult<String> {
    let now = date::get_chrono_local_now_time_str();
    let dir = format!("files/{}", &(now.replace(" ", "-"))[0..13]);
    to_global_result(file_util::create_dir_all(dir.as_str()))?;
    let path: String = format!("{}/{}", dir, file_name);

    Ok(path)
}
